import 'dart:async';
import 'package:sqflite_common/sqlite_api.dart' as sqflite;
import "package:froom/froom.dart";
import 'package:froom_common/src/util/primary_key_helper.dart';
import '../page/page_request.dart';
import '../page/page_result.dart';
import '../page/sort.dart';
import '../cnd/cndlib.dart';

/// 基础DAO抽象类
///
/// 提供基于泛型的通用数据库查询方法
/// 专注于查询构建、分页查询、条件查询等增强功能
///
abstract class BaseDao<T> {
  BaseDao(
    this.database,
    this.changeListener,
    this.tableName,
    this.primaryKeys,
    this.toMap,
    this.toEntity,
    this.field2Col,
  )   : queryAdapter = QueryAdapter(database, changeListener),
        insertionAdapter =
            InsertionAdapter(database, tableName, toMap, changeListener),
        updateAdapter = UpdateAdapter(
            database, tableName, primaryKeys, toMap, changeListener),
        deletionAdapter = DeletionAdapter(
            database, tableName, primaryKeys, toMap, changeListener);

  /// 获取数据库实例
  final sqflite.DatabaseExecutor database;

  final StreamController<String> changeListener;

  final QueryAdapter queryAdapter;

  final InsertionAdapter<T> insertionAdapter;

  final UpdateAdapter<T> updateAdapter;

  final DeletionAdapter<T> deletionAdapter;

  /// 获取表名
  final String tableName;

  final Map<String, Object?> Function(T) toMap;

  final T Function(Map<String, Object?>) toEntity;

  /// 获取主键字段名
  final List<String> primaryKeys;

  final Map<String, String> field2Col;
// ==================== 基础操作 ====================

  Future<int> insert(T entity) async {
    return insertionAdapter.insertAndReturnId(entity, OnConflictStrategy.abort);
  }

  Future<List<int>> inserts(List<T> entitys) async {
    return insertionAdapter.insertListAndReturnIds(
        entitys, OnConflictStrategy.abort);
  }

  Future<void> update(T entity) async {
    await updateAdapter.update(entity, OnConflictStrategy.abort);
  }

  Future<void> updates(List<T> entitys) async {
    await updateAdapter.updateList(entitys, OnConflictStrategy.abort);
  }

  Future<int> delete(T entity) async {
    return deletionAdapter.deleteAndReturnChangedRows(entity);
  }

  Future<int> deletes(List<T> entitys) async {
    return deletionAdapter.deleteListAndReturnChangedRows(entitys);
  }

  /// 根据主键删除（工具方法）
  ///
  /// 参数:
  /// - [id]: 主键值
  ///
  /// 返回: 完成删除操作的 Future
  Future<void> deleteById(dynamic id) async {
    await database.delete(
      tableName,
      where: PrimaryKeyHelper.getWhereClause(primaryKeys),
      whereArgs: [id],
    );
  }

  /// 根据主键查找实体
  Future<T?> findById(dynamic id) async {
    final List<Map<String, dynamic>> maps = await database.query(
      tableName,
      where: PrimaryKeyHelper.getWhereClause(primaryKeys),
      whereArgs: [id],
      limit: 1,
    );

    if (maps.isEmpty) return null;
    return toEntity(maps.first);
  }

  /// 检查实体是否存在
  Future<bool> exists(dynamic id) async {
    final T? en = await findById(id);
    return en != null;
  }

  /// 根据主键删除（工具方法）
  ///
  /// 参数:
  /// - [id]: 主键值
  ///
  /// 返回: 完成删除操作的 Future
  Future<void> deleteByPrimary(Map<String, Object> primaryValues) async {
    await database.delete(
      tableName,
      where: PrimaryKeyHelper.getWhereClause(primaryKeys),
      whereArgs:
          PrimaryKeyHelper.getPrimaryKeyValues(primaryKeys, primaryValues),
    );
  }

  /// 根据主键查找实体
  Future<T?> findByPrimary(Map<String, Object> primaryValues) async {
    final List<Map<String, dynamic>> maps = await database.query(
      tableName,
      where: PrimaryKeyHelper.getWhereClause(primaryKeys),
      whereArgs:
          PrimaryKeyHelper.getPrimaryKeyValues(primaryKeys, primaryValues),
      limit: 1,
    );

    if (maps.isEmpty) return null;
    return toEntity(maps.first);
  }

  /// 检查实体是否存在
  Future<bool> existsPrimary(Map<String, Object> primaryValues) async {
    final T? en = await findByPrimary(primaryValues);
    return en != null;
  }

  /// 查找所有实体
  Future<List<T>> findAll() async {
    final List<Map<String, dynamic>> maps = await database.query(tableName);
    return maps.map((map) => toEntity(map)).toList();
  }

// ==================== 条件查询 ====================

  /// 根据条件查询实体列表
  Future<List<T>> findByCnd(
      List<Cnd> cndList, Map<String, dynamic> dataMap) async {
    final cndResult = CndUtil.buildCnd(cndList, dataMap, field2Col);

    if (!cndResult.hasCnds) {
      return findAll();
    }

    final List<Map<String, dynamic>> maps = await database.query(
      tableName,
      where: cndResult.whereClause,
      whereArgs: cndResult.parameters,
    );

    return maps.map((map) => toEntity(map)).toList();
  }

  /// 根据条件查询单个实体
  Future<T?> findOneByCnd(
      List<Cnd> cndList, Map<String, dynamic> dataMap) async {
    final cndResult = CndUtil.buildCnd(cndList, dataMap, field2Col);

    String? whereClause;
    List<dynamic>? whereArgs;

    if (cndResult.hasCnds) {
      whereClause = cndResult.whereClause;
      whereArgs = cndResult.parameters;
    }

    final List<Map<String, dynamic>> maps = await database.query(
      tableName,
      where: whereClause,
      whereArgs: whereArgs,
      limit: 1,
    );

    if (maps.isEmpty) return null;
    return toEntity(maps.first);
  }

  /// 根据条件统计数量
  Future<int> countByCnd(
      List<Cnd> cndList, Map<String, dynamic> dataMap) async {
    final cndResult = CndUtil.buildCnd(cndList, dataMap, field2Col);

    String? whereClause;
    List<dynamic>? whereArgs;

    if (cndResult.hasCnds) {
      whereClause = cndResult.whereClause;
      whereArgs = cndResult.parameters;
    }

    final List<Map<String, dynamic>> result = await database.query(
      tableName,
      columns: ['COUNT(*) as count'],
      where: whereClause,
      whereArgs: whereArgs,
    );

    return result.first['count'] as int;
  }

// ==================== 分页查询 ====================

  /// 分页查询所有实体
  Future<PageResult<T>> findByPage(PageRequest pageRequest) async {
// 查询总数
    final List<Map<String, dynamic>> countResult = await database.query(
      tableName,
      columns: ['COUNT(*) as count'],
    );
    final totalElements = countResult.first['count'] as int;

// 查询数据
    final offset = (pageRequest.pageNumber - 1) * pageRequest.pageSize;
    final List<Map<String, dynamic>> maps = await database.query(
      tableName,
      limit: pageRequest.pageSize,
      offset: offset,
      orderBy: _buildOrderBy(pageRequest.sort),
    );

    final content = maps.map((map) => toEntity(map)).toList();

    return PageResult<T>(
      content: content,
      pageReq: pageRequest,
      totalElements: totalElements,
    );
  }

// ==================== 条件+分页组合查询 ====================

  /// 根据条件进行分页查询
  Future<PageResult<T>> findByCndAndPage(
    List<Cnd> cndList,
    Map<String, dynamic> dataMap,
    PageRequest pageRequest,
  ) async {
    final cndResult = CndUtil.buildCnd(cndList, dataMap, field2Col);

    String? whereClause;
    List<dynamic>? whereArgs;

    if (cndResult.hasCnds) {
      whereClause = cndResult.whereClause;
      whereArgs = cndResult.parameters;
    }

// 查询总数
    final List<Map<String, dynamic>> countResult = await database.query(
      tableName,
      columns: ['COUNT(*) as count'],
      where: whereClause,
      whereArgs: whereArgs,
    );
    final totalElements = countResult.first['count'] as int;

// 查询数据
    final offset = (pageRequest.pageNumber - 1) * pageRequest.pageSize;
    final List<Map<String, dynamic>> maps = await database.query(
      tableName,
      where: whereClause,
      whereArgs: whereArgs,
      limit: pageRequest.pageSize,
      offset: offset,
      orderBy: _buildOrderBy(pageRequest.sort),
    );

    final content = maps.map((map) => toEntity(map)).toList();

    return PageResult<T>(
      content: content,
      pageReq: pageRequest,
      totalElements: totalElements,
    );
  }

// ==================== 条件更新和删除 ====================

  /// 根据条件更新实体
  Future<int> updateByCnd(
    Map<String, Object> setDataMap,
    List<Cnd> whereCndList,
    Map<String, dynamic> whereDataMap,
  ) async {
    final whereResult = CndUtil.buildCnd(whereCndList, whereDataMap, field2Col);
    return await database.update(tableName, setDataMap,
        where: whereResult.whereClause, whereArgs: whereResult.parameters);
  }

  /// 根据条件删除实体
  Future<int> deleteByCnd(
      List<Cnd> cndList, Map<String, dynamic> dataMap) async {
    final cndResult = CndUtil.buildCnd(cndList, dataMap, field2Col);

    if (!cndResult.hasCnds) {
      throw ArgumentError('Delete conditions cannot be empty for safety');
    }

    return await database.delete(
      tableName,
      where: cndResult.whereClause,
      whereArgs: cndResult.parameters,
    );
  }

// ==================== 辅助方法 ====================

  /// 构建排序子句
  String? _buildOrderBy(Sort sort) {
    if (sort.orders.isEmpty) return null;

    return sort.orders.map((order) {
      final direction = order.direction == Direction.asc ? 'ASC' : 'DESC';
      return '${order.property} $direction';
    }).join(', ');
  }
}
